﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data.Linq;
using DTC.Converters;
using lpsolve55;

namespace DTC.Database
{
    public partial class DTCPatient
    {

        public string FullName
        {
            get
            {
                return this.Surname + " " + this.Name + " " + this.Fathername;
            }
        }
        public void Insert()
        {
            App.DBI.Db.DTCPatients.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCPatients.DeleteOnSubmit(this);
            var parents = this.DTCParents;
            var drugPrescriptions = this.DTCDrugPrescriptions;
            var prescriptionOrders = from po in App.DBI.Db.DTCPatientOrders
                                     where po.DTCDrugPrescription.PatientID == this.PatientID
                                     select po;

            var orderedBoxes = from ob in App.DBI.Db.DTCPatientOrderedBoxes
                               where prescriptionOrders.Any(po => ob.PatientOrderID == po.PatienOrderID)
                               select ob;

            App.DBI.Db.DTCPatientOrderedBoxes.DeleteAllOnSubmit(orderedBoxes);
            App.DBI.Db.DTCPatientOrders.DeleteAllOnSubmit(prescriptionOrders);
            App.DBI.Db.DTCDrugPrescriptions.DeleteAllOnSubmit(drugPrescriptions);
            App.DBI.Db.DTCParents.DeleteAllOnSubmit(parents);

            App.DBI.Db.SubmitChanges();
        }

        partial void OnSurnameChanged()
        {
            SendPropertyChanged("FullName");

        }
        partial void OnNameChanged()
        {
            this.SendPropertyChanged("FullName");
        }
        partial void OnFathernameChanged()
        {
            this.SendPropertyChanged("FullName");

        }
    }
    
    public partial class DTCVisit
    {
        private VisitVisual visual;
        public VisitVisual Visual
        {
            get
            {
                return visual;
            }
            set
            {
                if (visual != value)
                {
                    visual = value;
                    //visual.Owner = this;
                }
            }
        }

    }
   
    public partial class DTCDisease
    {
        public void Insert()
        {
            App.DBI.Db.DTCDiseases.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public string FullName
        {
            get
            {
                return (string)new DTCDiseaseToStringConverter().ConvertBack(this);
            }
        }
    }
    
    public partial class DTCInsuranceCompany
    {
        public void Insert()
        {
            App.DBI.Db.DTCInsuranceCompanies.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCPhone
    {
        public void Insert()
        {
            App.DBI.Db.DTCPhones.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCPhones.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCParent
    {
        public string FullName
        {
            get
            {
                return this.Name + " " + this.Fathername + ", " + this.Status;
            }
        }
        public void Insert()
        {
            App.DBI.Db.DTCParents.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCParents.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }

        partial void OnSurnameChanged()
        {
            SendPropertyChanged("FullName");

        }
        partial void OnNameChanged()
        {
            this.SendPropertyChanged("FullName");
        }
        partial void OnFathernameChanged()
        {
            this.SendPropertyChanged("FullName");

        }
        partial void OnStatusChanged()
        {
            this.SendPropertyChanged("FullName");

        }
    }
    
    public partial class DTCAddress
    {
        public void Insert()
        {
            App.DBI.Db.DTCAddresses.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCAddresses.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCCity
    {
        public void Insert()
        {
            App.DBI.Db.DTCCities.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCRegion
    {
        public void Insert()
        {
            App.DBI.Db.DTCRegions.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCDistrict
    {
        public void Insert()
        {
            App.DBI.Db.DTCDistricts.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCStreet
    {
        public void Insert()
        {
            App.DBI.Db.DTCStreets.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
    }
    
    public partial class DTCDoctor
    {
        public string FullName
        {
            get
            {
                return this.Surname + " " + this.Name + " " + this.Fathername;

            }
        }
        public void Insert()
        {
            App.DBI.Db.DTCDoctors.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            List<DTCPatient> pats = this.DTCPatients.ToList();
            foreach (DTCPatient pat in pats)
                pat.DTCDoctor = null;
            App.DBI.Db.DTCDoctors.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Copy(DTCDoctor Doctor)
        {
            this.DoctorID = Doctor.DoctorID;
            this.Surname = Doctor.Surname;
            this.Name = Doctor.Name;
            this.Fathername = Doctor.Fathername;
            this.DTCSpecialization = Doctor.DTCSpecialization;
        }

        partial void OnSurnameChanged()
        {
            SendPropertyChanged("FullName");

        }
        partial void OnNameChanged()
        {
            this.SendPropertyChanged("FullName");
        }
        partial void OnFathernameChanged()
        {
            this.SendPropertyChanged("FullName");

        }
    }
    
    public partial class DTCSpecialization
    {
        public void Insert()
        {
            App.DBI.Db.DTCSpecializations.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }

        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
    }


    //Все, что касается системы учета препаратов
    #region Drugs
    public partial class DTCDrug
    {
        public void Insert()
        {
            App.DBI.Db.DTCDrugs.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            foreach (var drugUnit in DTCDrugUnits)
            {
                drugUnit.Delete();
            }
            App.DBI.Db.DTCDrugs.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel(this);
        }

        public List<DrugNeeded> requeredDrugs;
        public bool CanBeDeleted
        {
            get
            {
                foreach (var drugUnit in DTCDrugUnits)
                {
                    if (!drugUnit.CanBeDeleted)
                        return false;
                }
                return true;
            }
        }
        //.///sdfsdf
        public List<DrugNeeded> RequeredDrugs
        {
            get
            {
                if (requeredDrugs == null)
                    requeredDrugs = new List<DrugNeeded>();
                return requeredDrugs;
            }
            set
            {
                if (requeredDrugs != value)
                    requeredDrugs = value;
            }
        }       

    }

    public partial class DTCDrugUnit
    {
        public void Insert()
        {

            //temp stuff
            App.DBI.Db.DTCDrugUnits.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            if (!CanBeDeleted)
            {
                throw new InvalidOperationException(string.Format("Не возможно удалить препарать {0}", FullName));   
            }
            foreach (var box in DTCBoxes)
            {
                box.Delete();
            }
            App.DBI.Db.DTCDrugUnits.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel(this);
        }
        public string FormatedValue //форматирование строки, на подобии того, что бы прибавлять мг, мкг, л, мл и пр.
        {
            get
            {
                if (this.Value == null)
                    return "";

                string unitSign = this.DTCIssueForm.MesaureUnitAcronym;
                string valSig = DTCIssueForm.ValSignParser(this.Value);
                return valSig + unitSign;

            }
            set
            {
                string str = value;
                string val = "";
                string acr = "";
                double multiplier = 1.0;
                for (int i = 0; i < str.Length; i++)
                {
                    if (char.IsDigit(str[i]))
                        val += str[i];
                    if (char.IsLetter(str[i]))
                        acr += str[i];
                }
                multiplier = DTCIssueForm.SiParser(acr);
                double dval;
                double.TryParse(val, out dval);
                dval = dval * multiplier;
                this.Value = dval;
            }
        }
        public string FullName
        {
            get
            {
                string result = "";
                if (this.DTCIssueForm.IsDiscret != null)
                {
                    if (this.DTCIssueForm.IsDiscret == true)
                        result = this.DTCDrug.Name + ", " + this.DTCIssueForm.Name + ", " + this.FormatedValue;
                    else
                        result = this.DTCDrug.Name + ", " + this.DTCIssueForm.Name;
                }
                return result;
            }
        }
        public string IssueFormName
        {
            get
            {
                string result = "";
                if (this.DTCIssueForm.IsDiscret != null)
                {
                    if (this.DTCIssueForm.IsDiscret == true)
                        result = this.DTCIssueForm.Name + ", " + this.FormatedValue;
                    else result = this.DTCIssueForm.Name;
                }
                return result;
            }
        }

        public bool CanBeDeleted
        {
            get
            {
                if(this.DTCDrugPrescriptions.Count != 0)
                    return false;
                if (this.DTCBoxes.Count == 0)
                    return true;
                foreach (var box in DTCBoxes)
                {
                    if (!box.CanBeDeleted)
                        return false;
                }
                return true;
            }
        }
    }  

    public partial class DTCOrderedBox
    {
    }
    

    public partial class DTCBox
    {

        public void Update()
        {
        }

        public void Insert()
        {
           
        }

        private string log = "";
        private DTCDrug drug = new DTCDrug();
        public DTCDrug Drug
        {
            get
            {
                if(this.DTCDrugUnit != null)
                        return this.DTCDrugUnit.DTCDrug;
                return null;
            }
        }

        public DTCManufacturer Manufacturer
        {
            get
            {
                return this.DTCManufacturer;
            }
        }
        public DTCIssueForm IssueForm
        {
            get
            {
                return this.DTCDrugUnit.DTCIssueForm;
            }
        }

        public string IssueFormName
        {
            get
            {
                return this.DTCDrugUnit.DTCIssueForm.Name;
            }
        }

        public string DrugValue
        {
            get
            {
                if (DTCDrugUnit != null)
                    return DTCDrugUnit.FormatedValue;
                else return "";
            }
            set
            {
                if(DTCDrugUnit != null)
                if (DTCDrugUnit.FormatedValue != value)
                    DTCDrugUnit.FormatedValue = value;
            }
        }
        public double DrugAmount
        {
            get
            {
                return this.UnitCount.Value * this.DTCDrugUnit.Value.Value;
            }
        }

  

        
        public void Delete()
        {
            if (DTCPatientOrderedBoxes.Count != 0 || DTCOrderedBoxes.Count != 0)
                throw new InvalidOperationException(string.Format("Не возможно удалить упаковку {0}", FullName));
            App.DBI.Db.DTCSuplierPrices.DeleteAllOnSubmit(DTCSuplierPrices);
            App.DBI.Db.DTCBoxes.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel();
        }


        public string FullName
        {
            get
            {
                string result =  this.DTCDrugUnit.FullName;
                if (this.DTCDrugUnit.DTCIssueForm != null)
                {
                    if (this.DTCDrugUnit.DTCIssueForm.IsDiscret != null)
                    {
                        if (this.DTCDrugUnit.DTCIssueForm.IsDiscret == true)
                            result += " - " + this.UnitCount.ToString() + " шт.";
                        else
                        {
                            result += ", " + (string)new SiStringToDoubleConverter().ConvertTo(this.UnitCount) + this.DTCDrugUnit.DTCIssueForm.MesaureUnitAcronym;
                        }
                    }
                }
                return result;
            }
        }
        public string FormatedDrug
        {
            get
            {
                if (this.DTCDrugUnit == null)
                    return "";
                if (this.DTCDrugUnit.DTCIssueForm == null)
                    return "";
                if (this.DTCDrugUnit.DTCDrug == null) 
                    return "";
                if (this.DTCDrugUnit.DTCIssueForm.IsDiscret == null)
                    return "";
                if(this.DTCDrugUnit.DTCIssueForm.IsDiscret == true)
                {
                    return this.UnitCount.ToString() + " шт. по " + DTCDrugUnit.FormatedValue;
                }
                else
                {
                    return (string)new SiStringToDoubleConverter().ConvertTo(this.UnitCount) + this.DTCDrugUnit.DTCIssueForm.MesaureUnitAcronym;
                }
            }
        }

        public bool CanBeDeleted
        {
            get
            {
                if (this.DTCPatientOrderedBoxes.Count != 0)
                    return false;
                if(this.DTCDrugStore != null)
                    return false;
                if(this.DTCOrderedBoxes.Count != 0)
                    return false;
                return true;
            }
        }

    }

    public partial class DTCPatientOrderedBox
    {
        /// <summary>
        /// Возвращает название упаковки и количество заказанных упаковок
        /// </summary>
        public string BoxCount
        {
            get
            {
                return DTCBox.FormatedDrug + " " + Count.ToString();
            }
        }

        partial void OnCountChanged()
        {
            if (DTCPatientOrder != null)
                if (DTCPatientOrder.DTCOrder != null)
                    DTCPatientOrder.DTCOrder.TotalChanged();
        }
    }

    public partial class DTCIssueForm
    {
        public void Insert()
        {
            App.DBI.Db.DTCIssueForms.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCDrugUnits.DeleteAllOnSubmit(this.DTCDrugUnits);
            App.DBI.Db.DTCIssueForms.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel(this);
        }
        public static string ValSignParser(double? value)
        {
            if (value == null)
                return "";
            SiPrefixValueComparer spcv = new SiPrefixValueComparer();
            SiPrefixes.Sort(spcv);
            if (value < 1 && value >= SiPrefixes[0].Value)
                return (value / SiPrefixes[0].Value).ToString() + " " + SiPrefixes[0].Name;
            for (int i = 1; i < SiPrefixes.Count; i++)
            {
                if (value < SiPrefixes[i - 1].Value && value >= SiPrefixes[i].Value)
                    return (value / SiPrefixes[i].Value).ToString() + " " + SiPrefixes[i].Name;
            }
            return value.ToString() + " ";
        }
        public static double SiParser(string str)
        {
            int i = 0;
            int length = -1;
            SiPrefixNameComparer spc = new SiPrefixNameComparer();
            SiPrefixes.Sort(spc);
            foreach (SiPrefix sp in SiPrefixes)
            {
                if (str.Contains(sp.Name))
                    return sp.Value;
            }
            return 1;
        }
        public static List<SiPrefix> SiPrefixes = new List<SiPrefix>() 
                        { 
                            new SiPrefix() {Name="м", Value=0.001},
                            new SiPrefix() {Name="мк", Value=0.000001}
                        };

        public bool CanBeDeleted
        {
            get
            {
                foreach (var drugUnit in DTCDrugUnits)
                {
                    if (!drugUnit.CanBeDeleted)
                        return false;
                }
                return true;
            }
        }
    }    
   
    public partial class DTCSupplier
    {
        public void Insert()
        {
            App.DBI.Db.DTCSuppliers.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCSuppliers.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel(this);
        }
    }

    public partial class DTCManufacturer
    {
        public void Insert()
        {
            App.DBI.Db.DTCManufacturers.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCManufacturers.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel(this);
        }

        public List<DTCDrug> ManufacturedDrugs
        {
            get
            {
                List<DTCDrug> result = new List<DTCDrug>();
                foreach (DTCBox tempBox in this.DTCBoxes)
                {
                    result.Add(tempBox.Drug);
                }
                return result;
            }
        }
    }

    public partial class DTCFreqOfUse
    {
        public int NumberOfUses(int HoursFromCycleBegining, int HoursPeriod)
        {
            if (DTCDrugUsePeriods.Count == 0)
                return 0;
            if (DTCDrugUsePeriods.Count == 1)
            {
                if (DTCDrugUsePeriods[0].Period.Value != 0)
                {
                    return (int)(((double)HoursPeriod) / DTCDrugUsePeriods[0].Period.Value);
                }
                else return 0;
            }
            List<DTCDrugUsePeriod> periods = this.DTCDrugUsePeriods.OrderBy(p => p.CycleIndex).ToList();
            
            //отсортировать по возростанию время начала ??? когда вообще начинается конкретная фаза?

            //Определяем фазу цикла, которая является 
            //начальной для расчитываемого периода времени
            double FullCycleLenght=0;
            int UseCount = 0;
            foreach (DTCDrugUsePeriod dup in periods)
            {
                FullCycleLenght += dup.DurationHours.Value;
            }
            int FullCycleCountFormBegining = (int)((double)HoursFromCycleBegining / FullCycleLenght);
            double HoursFromCurrentCycleBegining = HoursFromCycleBegining - ((double)FullCycleCountFormBegining*FullCycleLenght);
            int CurrentPhaseIndex = 0;
            double CurrentPhaseLeftTime = 0;
            double CurrentPhaseStartTime = 0;
            foreach (DTCDrugUsePeriod dup in periods)
            {
                CurrentPhaseStartTime +=(int)dup.DurationHours.Value;
                if (CurrentPhaseStartTime > HoursFromCurrentCycleBegining)
                {
                    CurrentPhaseStartTime -= (int)dup.DurationHours.Value;
                    break;
                }
                CurrentPhaseIndex++;
            }

            
            //расчет количества приемов на оставшемся промежутки времени для начальной фазы с учетом того
            //что начало может приходиться на любой момент времени, в интервале времени начальной фазы
            CurrentPhaseLeftTime = periods[CurrentPhaseIndex].DurationHours.Value - (HoursFromCurrentCycleBegining - CurrentPhaseStartTime);
            if (periods[CurrentPhaseIndex].Period != 0)
            {
                //округление до меньшего целого инта???? нормально или нет?
                UseCount = (int)(((double)CurrentPhaseLeftTime) / periods[CurrentPhaseIndex].Period.Value);
            }
            CurrentPhaseStartTime += (int)periods[CurrentPhaseIndex].DurationHours.Value;
            if (CurrentPhaseIndex == periods.Count - 1)
                CurrentPhaseIndex = 0;
            else CurrentPhaseIndex++;
            

            //условие цикла немного мутновато. Точнее правая часть
            //смысл таков: пока конец текущей фазы вписываеся в заданный период времени, считаем
            //если вошел ровно, то хвоста нет, следующий за циклом блок if{} не срабатывает
            double CurrentFreqStartTime = HoursFromCycleBegining - ((double)FullCycleCountFormBegining * FullCycleLenght);
            while (CurrentPhaseStartTime + periods[CurrentPhaseIndex].DurationHours <= (CurrentFreqStartTime + HoursPeriod))
            {
                if (periods[CurrentPhaseIndex].Period != 0)
                {
                    //опять таки округляется до целого, меньшего целого. Нормально???
                    UseCount += (int)(periods[CurrentPhaseIndex].DurationHours / periods[CurrentPhaseIndex].Period);
                }
                CurrentPhaseStartTime += (int)periods[CurrentPhaseIndex].DurationHours.Value;
                if (CurrentPhaseIndex == periods.Count - 1)
                    CurrentPhaseIndex = 0;
                else CurrentPhaseIndex++;
            }
            //подбираем правый хвост
            if ((CurrentFreqStartTime + HoursPeriod) > CurrentPhaseStartTime + periods[CurrentPhaseIndex].DurationHours)
            {
                CurrentPhaseStartTime += (int)periods[CurrentPhaseIndex].DurationHours.Value;
                CurrentPhaseIndex++;
                CurrentPhaseLeftTime = (HoursFromCycleBegining + HoursPeriod) - CurrentPhaseStartTime;
                if (periods[CurrentPhaseIndex].Period != 0)
                    UseCount += (int)(CurrentPhaseLeftTime / periods[CurrentPhaseIndex].Period);
            }
            return UseCount;
        }
        public string FormatedFreq
        {
            get
            {
                string result ="";
                if (this.TimeTo.Value != (this.DTCDrugPrescription.CourseStartDate.Value.AddDays(this.DTCDrugPrescription.CourseDurationDays.Value)))
                    result = "[" + (string)new TimeSpanToStringConverter().ConvertTo(this.TimeTo.Value - this.TimeFrom.Value, typeof(string)) + "]: ";
                List<DTCDrugUsePeriod> Dups = this.DTCDrugUsePeriods.OrderBy(d => d.CycleIndex).ToList();
                foreach (DTCDrugUsePeriod dup in Dups)
                {
                    result += (string)new FreqOfUsePeriodToString().Convert(dup);
                    if(Dups.IndexOf(dup) != Dups.Count-1)
                        result += "-";
                }
                return result;
            }
        }
    }

    public partial class DTCDrugPrescription
    {
        public void Delete()
        {
            if (this.DTCFreqOfUses != null)
            {
                if (this.DTCFreqOfUses.Count != 0)
                {
                    foreach (DTCFreqOfUse fou in this.DTCFreqOfUses)
                    {
                        if (fou.DTCDrugUsePeriods != null)
                        {
                            if (fou.DTCDrugUsePeriods.Count != 0)
                                fou.DTCDrugUsePeriods.Clear();
                        }
                    }
                    this.DTCFreqOfUses.Clear();
                }
            }
            if (this.DTCDrugDoses != null)
            {
                if (this.DTCDrugDoses.Count != 0)
                {
                    this.DTCDrugDoses.Clear();
                }
            }
            App.DBI.Db.DTCDrugPrescriptions.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        #region Расчет потребности на указанный период

        public List<DrugNeeded> DrugNeed(DateTime From, DateTime To)
        {
            if (this.DTCDrugUnit == null)
                return null;
            if (!this.DTCDrugUnit.Value.HasValue)
                return null;
            if (this.DTCFreqOfUses.Count == 0)
                return null;
            if (this.DTCDrugDoses.Count == 0)
                return null;
            DateTime[] dates = GetAllTimeIntervals(From, To);
            List<DrugNeeded> result = null;
            double needCount = 0;
            double dose;
            double number;
            DTCDrugPrescription bla = this;
            List<DTCFreqOfUse> blaf = this.DTCFreqOfUses.ToList();
            List<DTCDrugDose> blad = this.DTCDrugDoses.ToList();
            for (int i = 0; i < dates.Count() - 1; i++)
            {

                dose = DoseOnTime(dates[i]);
                number = NumberOfUses(dates[i], dates[i + 1]);
                //количество едениц, необходимых употребить
                needCount += dose * number;
            }

            //Вичетаем остаток после последней выдачи
            needCount -= this.DrugsLeftOnLasIssue();

            if (needCount != 0)
            {
                //посчитать количество пачек или коробок или унитов
                result = RoundNeed(this.DTCDrugUnit, needCount);
                
            }
            return result;
        }
        public double DoseOnTime(DateTime t)
        {
            double Dose = 0;
            double MaxDose=0;
            foreach (DTCDrugDose dd in DTCDrugDoses)
            {
                if (dd.TimeFrom == null || dd.TimeTo == null)
                    continue;
                if (t >= dd.TimeFrom && t < dd.TimeTo)
                    if (dd.Value != null)
                    {
                        Dose = dd.Value.Value;
                        if (MaxDose <= Dose)
                            MaxDose = Dose;
                    }
            }
            return Dose / this.DTCDrugUnit.Value.Value;
        }
        public double NumberOfUses(DateTime TimeFrom, DateTime TimeTo)
        {
            if (this.DTCFreqOfUses == null)
                return 0;
            double result = 0;
            DateTime PeriodStartTime;
            DateTime PeriodEndTime;
            foreach (DTCFreqOfUse fou in this.DTCFreqOfUses)
            {
                if (fou.TimeFrom == null || fou.TimeTo == null)
                    continue;
                if (TimeFrom.Date >= fou.TimeFrom.Value.Date
                                    &&
                    TimeFrom.Date < fou.TimeTo.Value.Date
                                    ||
                    TimeTo.Date > fou.TimeFrom.Value.Date
                                    &&
                    TimeFrom.Date <= fou.TimeTo.Value.Date)
                {
                    if (TimeFrom.Date > fou.TimeFrom.Value.Date)
                        PeriodStartTime = TimeFrom;
                    else PeriodStartTime = fou.TimeFrom.Value;
                    if (TimeTo.Date < fou.TimeTo.Value.Date)
                        PeriodEndTime = TimeTo;
                    else PeriodEndTime = fou.TimeTo.Value;
                    result += fou.NumberOfUses((int)(PeriodStartTime - fou.TimeFrom.Value).TotalHours,(int) (PeriodEndTime - PeriodStartTime).TotalHours);
                }

            }
            return result;
        }
        private DateTime[] GetAllTimeIntervals(DateTime From, DateTime To)
        {
            List<DateTime> res = new List<DateTime>();
            res.Add(From);
            int i = 0;
            if (this.DTCDrugDoses != null)
            {
                foreach (DTCDrugDose dd in this.DTCDrugDoses)
                {
                    if (dd.TimeFrom.HasValue)
                    {
                        if (dd.TimeFrom.Value >= From && dd.TimeFrom.Value <= To)
                        {
                            if (!res.Contains(dd.TimeFrom.Value))
                                res.Add(dd.TimeFrom.Value);
                        }
                    }
                    if (dd.TimeTo.HasValue)
                    {
                        if (dd.TimeTo.Value >= From && dd.TimeTo.Value <= To)
                        {
                            if (!res.Contains(dd.TimeTo.Value))
                                res.Add(dd.TimeTo.Value);
                        }
                    }
                }
            }
            if (this.DTCFreqOfUses != null)
            {
                foreach (DTCFreqOfUse fou in this.DTCFreqOfUses)
                {
                    if (fou.TimeFrom.HasValue)
                    {
                        if (fou.TimeFrom.Value >= From && fou.TimeFrom.Value <= To)
                        {
                            if (!res.Contains(fou.TimeFrom.Value))
                                res.Add(fou.TimeFrom.Value);
                        }
                    }
                    if (fou.TimeTo.HasValue)
                    {
                        if (fou.TimeTo.Value >= From && fou.TimeTo.Value <= To)
                        {
                            if (!res.Contains(fou.TimeTo.Value))
                                res.Add(fou.TimeTo.Value);
                        }
                    }
                }
            }
            if (!res.Contains(To))
                res.Add(To);
            return res.OrderBy(date => date.Date).ToArray();
        }
        public double DrugsLeftOnLasIssue()
        {
            DateTime Last = this.CourseStartDate.Value;
            double result = 0;
            if (this.DTCDrugIssues != null)
            {
                foreach (DTCDrugIssue di in this.DTCDrugIssues)
                {
                    if (di.Date.HasValue)
                    {
                        if (di.Date.Value >= Last)
                        {
                            Last = di.Date.Value;
                            if (di.DosesLeft.HasValue)
                            {
                                result = di.DosesLeft.Value;
                            }
                        }
                    }
                }
            }
            return result;
        }
        partial void OnCourseStartDateChanged()
        {
            if (this.DTCFreqOfUses.Count != 0)
            {

                List<DTCFreqOfUse> freqs = this.DTCFreqOfUses.OrderBy(fr => fr.TimeFrom).ToList();
                TimeSpan diff = this.CourseStartDate.Value - freqs[0].TimeFrom.Value;
                foreach (DTCFreqOfUse fr in freqs)
                {
                    fr.TimeFrom += diff;
                    fr.TimeTo += diff;
                }
            }
            if (this.DTCDrugDoses.Count != 0)
            {
                List<DTCDrugDose> doses = this.DTCDrugDoses.OrderBy(ds => ds.TimeFrom).ToList();
                TimeSpan diff = this.CourseStartDate.Value - doses[0].TimeFrom.Value;
                foreach (DTCDrugDose ds in doses)
                {
                    ds.TimeFrom += diff;
                    ds.TimeTo += diff;
                }
            }
        }
        private List<DrugNeeded> RoundNeed(DTCDrugUnit unit, double count)
        {
            //Optimize here
            return OrderingSystem.CalculateBoxCount(unit, count);
            
        }
        public DTCDrugDose LastDosing
        {
            get
            {
                if (this.DTCDrugDoses.Count == 0)
                    return null;
                DTCDrugDose[] dd = this.DTCDrugDoses.OrderByDescending(d => d.TimeTo).ToArray();
                foreach (DTCDrugDose d in dd)
                {
                    if (d.DrugDoseID != 0)
                        return d;
                }
                return null;
            }
        }
        public DTCPatientOrder AddNewPatientOrder(DateTime From, DateTime To)
        {
            List<DrugNeeded> drugNeed = DrugNeed(From, To);
            if(drugNeed != null)
            {
                if(drugNeed.Count != 0)
                {
                    DTCPatientOrderedBox dob = null;
                    DTCPatientOrder po = new DTCPatientOrder();
                    po.DTCDrugPrescription = this;
                    foreach(DrugNeeded dn in drugNeed)
                    {
                        dob = new DTCPatientOrderedBox()
                        {
                            DTCBox = (DTCBox)dn.Drug,
                            Count = (int)dn.Count,
                           
                        };
                        po.DTCPatientOrderedBoxes.Add(dob);
                    }
                    return po;
                }
            }
            return null;
        }

   

        #endregion

        #region Элементы визуализации

        public string DrugName
        {
            get
            {
                return this.DTCDrugUnit.DTCDrug.Name;
            }
        }
        public DTCDrugDose DrugDose
        {
            get
            {
                if (this.DTCDrugDoses.Count() == 0)
                    this.DTCDrugDoses.Add(new DTCDrugDose(){TimeFrom = this.CourseStartDate, 
                        TimeTo=this.CourseStartDate.Value.Add(new TimeSpan(this.CourseDurationDays.Value, 0, 0, 0))});
                return this.DTCDrugDoses.OrderByDescending(d => d.TimeTo).FirstOrDefault(); 
            }
            set 
            {
                if (this.DTCDrugDoses.Count() == 0)
                    this.DTCDrugDoses.Add(value);
                else
                {
                    DTCDrugDose dd = this.DTCDrugDoses.OrderByDescending(d => d.TimeTo).FirstOrDefault();
                    dd = value;
                }
            }

        }

        public string IssueFormName
        {
            get
            {
                return this.DTCDrugUnit.DTCIssueForm.Name;
            }
        }
        public string FormatedDose
        {
            get
            {
                string result = "";
                List<DTCDrugDose> Doses = this.DTCDrugDoses.OrderBy(fr => fr.TimeFrom).ToList();
                foreach (DTCDrugDose dd in Doses)
                {
                    if (Doses.Count != 1)
                    {
                    }
                    result += DTCIssueForm.ValSignParser(dd.Value) + this.DTCDrugUnit.DTCIssueForm.MesaureUnitAcronym;
                    if (Doses.IndexOf(dd) != Doses.Count - 1)
                        result += "; ";
                }
                return result;
            }
            set
            {
                string str = value;
                string val = "";
                string acr = "";
                double multiplier = 1.0;
                for (int i = 0; i < str.Length; i++)
                {
                    if (char.IsDigit(str[i]))
                        val += str[i];
                    if (char.IsLetter(str[i]))
                        acr += str[i];
                }
                multiplier = DTCIssueForm.SiParser(acr);
                double dval;
                double.TryParse(val, out dval);
                dval = dval * multiplier;
                if (this.DTCDrugDoses.Count != 0)
                {
                    DateTime today = DateTime.Today;
                    if (LastDosing != null)
                    {
                        if (LastDosing.TimeTo.Value.Date > today.Date)
                            LastDosing.TimeTo = today;
                    }
                }
                DateTime StartDate = DateTime.Today;
                if (this.DTCDrugDoses.Count == 0)
                {
                    if(this.CourseStartDate.HasValue)
                        StartDate = this.CourseStartDate.Value;
                }
                DateTime EndDate = this.CourseStartDate.Value.AddDays(CourseDurationDays.Value);
                foreach (DTCPatientOrder po in this.DTCPatientOrders)
                {
                    if(po.DTCOrder!= null)
                        if((po.DTCOrder.DateFrom>=StartDate && po.DTCOrder.DateFrom<=EndDate)
                            ||
                            (po.DTCOrder.DateTo >=StartDate && po.DTCOrder.DateTo<=EndDate))
                        {
                            //////
                            //////
                            ////////
                            ///.. MEssed Up stuff here
                            po.DTCOrder.PatientOrderStatuse = App.DBI.GetStatusByID((int)DTCOrder.OrderStatuses.Changed);
                        }
                }
                DTCDrugDose dd = new DTCDrugDose()
                {
                    DTCDrugPrescription = this,
                    TimeFrom = StartDate,
                    TimeTo = EndDate,
                    Value = dval
                };
                List<DTCDrugDose> toDelete = new List<DTCDrugDose>();
                foreach (DTCDrugDose prevDose in this.DTCDrugDoses)
                {
                    if (dd.DrugDoseID != prevDose.DrugDoseID)
                    {
                        if ((dd.TimeFrom.Value == prevDose.TimeFrom.Value
                                            &&
                            dd.TimeTo.Value == prevDose.TimeTo.Value)
                                            ||
                            (prevDose.TimeFrom.Value == prevDose.TimeTo.Value)
                            )
                        {
                            toDelete.Add(prevDose);
                        }
                    }
                }
                foreach (DTCDrugDose d in toDelete)
                {
                    if(d.DrugDoseID != 0)
                        App.DBI.Db.DTCDrugDoses.DeleteOnSubmit(d);
                    this.DTCDrugDoses.Remove(d);
                }
                App.DBI.Db.DTCDrugDoses.InsertOnSubmit(dd);
                this.DTCDrugDoses.Add(dd);

            }
        }
        public string FormatedFreqOfUse
        {
            get
            {
                string result = "";
                List<DTCFreqOfUse> Freqs = this.DTCFreqOfUses.OrderBy(f => f.TimeTo).ToList();
                foreach(DTCFreqOfUse fu in Freqs)
                {
                    result += fu.FormatedFreq;
                    if (Freqs.IndexOf(fu) != Freqs.Count - 1)
                        result += "; ";
                }
                return result;
            }
            set
            {
                string[] freqs = value.Split(new char[] { ';' });
                DTCFreqOfUse fu;
                TimeSpan CurrentFreqTimeSpan = new TimeSpan(this.CourseDurationDays.Value, 0, 0, 0);
                int TimeFromCourseBegining=0;
                int TimeVal;
                string PeriodsSchemeString;
                string FreqPart;
                double TempPeriodVal;
                List<DTCDrugUsePeriod> periods = new List<DTCDrugUsePeriod>();
                DTCDrugUsePeriod tempPeriod;
                foreach (string freq in freqs)
                {
                    TimeVal=0;
                    PeriodsSchemeString="";
                    FreqPart="";
                    TempPeriodVal=0;
                    string[] substrings = freq.Split(new char[] { ':' });
                    int i =0;
                    if (substrings.Length == 2)
                    {
                        FreqPart = substrings[i].Trim(new char[] { '[', ']', ':', ' ' });
                        try
                        {
                            CurrentFreqTimeSpan = (TimeSpan)new TimeSpanToStringConverter().ConvertFrom(FreqPart, typeof(TimeSpan));
                        }
                        catch(Exception e)
                        {
                            throw e;
                        }
                        i++;
                    }
                    if (i == 0 && this.DTCFreqOfUses.Count != 0)
                    {
                        fu = new DTCFreqOfUse()
                        {
                            TimeFrom = DateTime.Today,
                            TimeTo = CourseStartDate.Value.AddDays(CourseDurationDays.Value)
                        };
                    }
                    else
                    {
                        fu = new DTCFreqOfUse()
                        {
                            TimeFrom = CourseStartDate.Value.AddDays(TimeFromCourseBegining),
                            TimeTo = CourseStartDate.Value.AddDays(TimeFromCourseBegining + CurrentFreqTimeSpan.Days),
                        };
                    }
                    TimeFromCourseBegining += CurrentFreqTimeSpan.Days;
                    PeriodsSchemeString = substrings[i].Trim(new char[] { ':', ' ' });
                    string[] PeriodsStrings = PeriodsSchemeString.Split(new char[] { '-' });
                    for (int j = 0; j < PeriodsStrings.Length; j++)
                    {

                        ///<summary>
                        ///простой парсер ритмов введения
                        ///</summary>
                        ///
                        /*try
                        {
                            int.TryParse(PeriodsStrings[j], out TimeVal);
                        }
                        catch(Exception e)
                        {
                            throw e;
                        }
                        if (TimeVal == 0)
                            TempPeriodVal = 0;
                        else
                            TempPeriodVal = 24.0 / (double)TimeVal;
                         */
                        tempPeriod = (DTCDrugUsePeriod) new FreqOfUsePeriodToString().ConvertBack(PeriodsStrings[j]);
                        tempPeriod.CycleIndex = j;
                        periods.Add(tempPeriod);
                    }
                    bool isAlreadyIn = false;
                    foreach (DTCFreqOfUse fr in this.DTCFreqOfUses)
                    {
                        isAlreadyIn = true;
                        if (fr.TimeFrom.Value == fu.TimeFrom.Value
                            &&
                            fr.TimeTo.Value == fu.TimeTo.Value)
                        {
                            if (fr.DTCDrugUsePeriods.Count != periods.Count)
                            {
                                isAlreadyIn = false;
                                continue;
                            }
                            else
                            {
                                foreach (DTCDrugUsePeriod checkPer1 in periods)
                                {
                                    foreach (DTCDrugUsePeriod checkPer2 in fr.DTCDrugUsePeriods)
                                    {
                                        if (checkPer1.CycleIndex.Value != checkPer2.CycleIndex.Value)
                                        {
                                            isAlreadyIn = false;
                                            break;
                                        }
                                        if (checkPer1.DurationHours.Value != checkPer2.DurationHours.Value)
                                        {
                                            isAlreadyIn = false;
                                            break;
                                        }
                                        if (checkPer1.Period.Value != checkPer2.Period.Value)
                                        {
                                            isAlreadyIn = false;
                                            break;
                                        }
                                    }
                                    if (!isAlreadyIn)
                                        break;
                                }
                            }                            
                        }
                        else
                        {
                            isAlreadyIn = false;
                        }
                        if (isAlreadyIn)
                            break;
                    }
                    if (!isAlreadyIn)
                    {
                        this.DTCFreqOfUses.Add(fu);
                        DateTime EndDate = this.CourseStartDate.Value.AddDays(CourseDurationDays.Value);
                        foreach (DTCPatientOrder po in this.DTCPatientOrders)
                        {
                            if(po.DTCOrder!= null)
                                if((po.DTCOrder.DateFrom>=fu.TimeFrom && po.DTCOrder.DateFrom<=fu.TimeTo)
                                    ||
                                    (po.DTCOrder.DateTo >=fu.TimeFrom && po.DTCOrder.DateTo<=fu.TimeTo))
                                {
                                    //////
                                    //////
                                    ////////
                                    ///.. MEssed Up stuff here
                                    po.DTCOrder.PatientOrderStatuse = App.DBI.GetStatusByID((int)DTCOrder.OrderStatuses.Changed);
                                }
                        }
                        App.DBI.Db.DTCFreqOfUses.InsertOnSubmit(fu);
                        fu.DTCDrugUsePeriods.AddRange(periods);
                        App.DBI.Db.DTCDrugUsePeriods.InsertAllOnSubmit(periods);
                        foreach (DTCFreqOfUse fr in this.DTCFreqOfUses)
                        {
                            if (fr.TimeFrom.Value >= fu.TimeFrom.Value
                                &&
                                fr.TimeTo.Value <= fu.TimeTo.Value
                                && 
                                fr.FreqOfUseID != fu.FreqOfUseID)
                            {
                                App.DBI.Db.DTCDrugUsePeriods.DeleteAllOnSubmit(fr.DTCDrugUsePeriods);
                                App.DBI.Db.DTCFreqOfUses.DeleteOnSubmit(fr);
                            }
                            if (fr.TimeFrom.Value < fu.TimeFrom.Value
                                            &&
                                fr.TimeTo.Value >= fu.TimeFrom.Value)
                                fr.TimeTo = fu.TimeFrom;
                        }
                    }
                    periods = new List<DTCDrugUsePeriod>();
                }
                
            }
        }
        public string FormatedUnitValue
        {
            get
            {
                return this.DTCDrugUnit.FormatedValue;
            }
        }

        public bool CanBeDeleted
        {
            get 
            {
                return this.DTCPatientOrders.Count == 0;
            }
        }

        #endregion
    }
    
    public partial class DTCDrugStore
    {
        public DTCDrug Drug
        {
            get
            {
                try
                {
                    return this.DTCBox.Drug;
                }
                catch
                {
                    return null;
                }
            }
        }
        public DTCManufacturer Manufacturer
        {
            get
            {
                try
                {
                    return this.DTCBox.DTCManufacturer;
                }
                catch
                {
                    return null;
                }
            }
        }
        public DTCIssueForm IssueForm
        {
            get
            {
                try
                {
                    return this.DTCBox.IssueForm;
                }
                catch
                {
                    return null;
                }
            }
        }
    }
    #endregion

    #region Классы по работе с системой заказов
    partial class DTCPatientOrder
    {
        public void Insert()
        {
            App.DBI.Db.DTCPatientOrders.InsertOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Update()
        {
            App.DBI.Db.SubmitChanges();
        }
        public void Delete()
        {
            App.DBI.Db.DTCPatientOrders.DeleteOnSubmit(this);
            App.DBI.Db.SubmitChanges();
        }
        public void Cancel()
        {
            App.DBI.ChangeCancel(this);
        }
    }

    partial class DTCOrder
    {

        public void TotalChanged()
        {
            SendPropertyChanged("TotalBoxCount");
        }

        public List<DrugNeeded> DrugNeed
        {
            get
            {
                return new List<DrugNeeded>();
            }
        }

        public List<DTCOrderedBox> TotalBoxCount
        {
            get
            {
                var boxes = new List<DTCOrderedBox>();
                foreach (var patientOrder in DTCPatientOrders)
                {
                    foreach (var box in patientOrder.DTCPatientOrderedBoxes)
                    {
                        var inbox = boxes.SingleOrDefault(b=>b.BoxID == box.BoxID);
                        if (inbox != null)
                            inbox.Count += box.Count;
                        else boxes.Add(new DTCOrderedBox(){DTCBox = box.DTCBox, Count = box.Count});
                    }
                }
                return boxes;
            }
        }
        public void SetPatientsOrders()
        {
            if (DateFrom == null || DateTo == null)
                return;
            List<DTCPatientOrder> newPatientOrders = new List<DTCPatientOrder>();
            List<DTCDrugPrescription> drugPrescriptions = App.DBI.GetActivePrescriptionsOnTimeInterval(DateFrom.Value, DateTo.Value);
            DTCPatientOrder newPatientOrder = null;
            foreach (DTCDrugPrescription presc in drugPrescriptions)
            {
                newPatientOrder = presc.AddNewPatientOrder(DateFrom.Value, DateTo.Value);
                if (newPatientOrder != null)
                {
                    if (newPatientOrder.DTCPatientOrderedBoxes != null)
                    {
                        this.DTCPatientOrders.Add(newPatientOrder);

                        List<DTCOrderedBox> newOrderBoxes = new List<DTCOrderedBox>();
                        bool WasFound = false;
                        foreach (DTCPatientOrderedBox dob in newPatientOrder.DTCPatientOrderedBoxes)
                        {
                            WasFound = false;
                            foreach (DTCOrderedBox ob in this.DTCOrderedBoxes)
                            {
                                if (dob.BoxID == ob.BoxID)
                                {
                                    ob.Count += dob.Count;
                                    WasFound = true;
                                    break;
                                }
                            }
                            if (!WasFound)
                            {
                                newOrderBoxes.Add(new DTCOrderedBox
                                 {
                                     DTCOrder = this,
                                     DTCBox = dob.DTCBox,
                                     Count = dob.Count
                                 });
                            }
                        }
                        if (newOrderBoxes.Count != 0)
                            this.DTCOrderedBoxes.AddRange(newOrderBoxes);
                    }
                }
            }
        }
        public void AddPatientOrder(DTCPatientOrder PatientOrder)
        {
            if (PatientOrder == null)
                return;
            if (PatientOrder.DTCOrder == this)
                return;
            if (PatientOrder.DTCPatientOrderedBoxes.Count == 0)
                return;
            PatientOrder.DTCOrder = this;
            bool WasFound = false;
            List<DTCOrderedBox> newBoxes = new List<DTCOrderedBox>();
            foreach (DTCPatientOrderedBox dob in PatientOrder.DTCPatientOrderedBoxes)
            {
                WasFound = false;
                foreach (DTCOrderedBox ob in this.DTCOrderedBoxes)
                {
                    if (ob.BoxID == dob.BoxID)
                    {
                        ob.Count += dob.Count;
                        WasFound = true;
                        break;
                    }
                }
                if(!WasFound)
                {
                    newBoxes.Add(new DTCOrderedBox()
                    {
                        DTCBox = dob.DTCBox,
                        Count = dob.Count,
                        DTCOrder = this
                    });
                }
                if(newBoxes.Count != 0)
                    this.DTCOrderedBoxes.AddRange(newBoxes);
                this.StatusID = (int)OrderStatuses.Changed;
            }
        }
        public void DeletePatientORder(DTCPatientOrder PatientOrder)
        {
            if (PatientOrder == null)
                return;
            if (PatientOrder.DTCOrder != this)
                return;
            bool ChangeWasMade = false;
            List<DTCOrderedBox> DeleteBoxes = new List<DTCOrderedBox>();
            foreach (DTCPatientOrderedBox dob in PatientOrder.DTCPatientOrderedBoxes)
            {
                foreach (DTCOrderedBox ob in this.DTCOrderedBoxes)
                {
                    if (ob.BoxID == dob.BoxID)
                    {
                        ob.Count -= dob.Count;
                        ChangeWasMade = true;
                        if (ob.Count <= 0)
                            DeleteBoxes.Add(ob);
                        break;
                    }
                }
            }
            if (ChangeWasMade)
            {
                if (DeleteBoxes.Count != 0)
                {
                    foreach (DTCOrderedBox ob in DeleteBoxes)
                        this.DTCOrderedBoxes.Remove(ob);
                }
                this.StatusID = (int)OrderStatuses.Changed;
            }
        }

        public enum OrderStatuses { Active=1, Added=2, Changed=3 };
    }
    #endregion

    //допольнительные классы, облегчающие и вносящие порядок
    //в работе некоторых процессов. Ну и просто 
    //необходимые для того что бы заработали некоторые функции
    #region AdditionalClasses
    //система заказов

    //вспомогательные классы для отображения в списках
    //и деревьях разнородных объектов (DTCDrugIssueForm, DTCDrugUnit,
    //DTCPack, DTCBox)(все эти объекты могут быт отображенны в одном элементе
    //фрэймворка)
    public class StoreDrug
    {
        public StoreDrug()
        {
            Drugs = new List<DTCBox>();
        }
        //список характеризуется некоторой стокой
        public string StoringForm { get; set; }
        public List<DTCBox> Drugs { get; set; }
    }
    public class DrugNeeded
    {
        public double Count { get; set; }
        public Object Drug { get; set; }
        public string DisplaidText
        {
            get
            {
                if (Drug is DTCDrug)
                    return (Drug as DTCDrug).Name +" - "+ Count;
                else if (Drug is DTCDrugUnit)
                    return (Drug as DTCDrugUnit).FullName + " - " + Count;
                else if (Drug is DTCBox)
                    return (Drug as DTCBox).FullName + " - " + Count;
                else return "";
            }
        }
    }

    //Правила сравнения
    public class SiPrefix
    {
        public string Name { get; set; }
        public double Value { get; set; }

    }
    public partial class OrderingSystem
    {
        public static List<DrugNeeded> CalculateBoxCount(DTCDrugUnit unit, double TotalNeed)
        {
            List<DTCBox> avaliableBoxes = AvailableBoxes(unit);
            avaliableBoxes = avaliableBoxes.OrderByDescending(b => b.DTCDrugUnit.Value).ToList();
            List<DrugNeeded> NeededBoxes = new List<DrugNeeded>();
           
            int lp;
            int i;

            int NAvOfBoxes = avaliableBoxes.Count; //количество доступных коробок
            if (NAvOfBoxes == 0)
                return null;
            double[] Rows;
            int[] Columns;

            lp = lpsolve.make_lp(0, NAvOfBoxes);
            if (lp == 0)
                return null;
            for (i = 0; i < NAvOfBoxes; i++)
            {
                lpsolve.set_col_name(lp, i + 1, "x" + (i + 1).ToString()); //указываем имена переменных
                lpsolve.set_int(lp, i + 1, true); //указываем тробование целочисленности
            }

            Rows = new double[NAvOfBoxes];
            Columns = new int[NAvOfBoxes];


            lpsolve.set_add_rowmode(lp, true);
            //указываем ограничение
            for (i = 0; i < NAvOfBoxes; i++)
            {
                Columns[i] = i + 1;
                Rows[i] = avaliableBoxes[i].UnitCount.Value;
            }
            if (lpsolve.add_constraintex(lp, i, ref Rows[0], ref Columns[0], lpsolve.lpsolve_constr_types.GE, TotalNeed) == false)
                return null;
            //указываем целевую функцию
            lpsolve.set_add_rowmode(lp, false);
            for (i = 0; i < NAvOfBoxes; i++)
            {
                Columns[i] = i + 1;
                Rows[i] = avaliableBoxes[i].UnitCount.Value + 1;
            }
            if (lpsolve.set_obj_fnex(lp, i, ref Rows[0], ref Columns[0]) == false)
                return null;
            lpsolve.set_minim(lp);
            lpsolve.lpsolve_return s = lpsolve.solve(lp);
            //if ( s != lpsolve.lpsolve_return.OPTIMAL)
            //   return false;
            lpsolve.get_variables(lp, ref Rows[0]);
            for (i = 0; i < NAvOfBoxes; i++)
            {
                if(Rows[i] != 0)
                    NeededBoxes.Add(new DrugNeeded() { Drug = avaliableBoxes[i], Count = (int)Rows[i] });
            }
            return NeededBoxes;
        }

        public static List<DTCBox>AvailableBoxes(DTCDrugUnit unit)
        {
            return unit.DTCBoxes.ToList();
        }
    }
    public class SiPrefixNameComparer : IComparer<SiPrefix>
    {
        public int Compare(SiPrefix x, SiPrefix y)
        {
            if (x == null || y == null)
                return 0;
            if (x.Name == null || y.Name == null)
                return 0;
            if (x.Name.Length == y.Name.Length)
                return 0;
            if (x.Name.Length > y.Name.Length)
                return -1;
            if (x.Name.Length < y.Name.Length)
                return 1;
            return 0;
        }
    }
    public class SiPrefixValueComparer : IComparer<SiPrefix>
    {
        public int Compare(SiPrefix x, SiPrefix y)
        {
            if (x == null || y == null)
                return 0;
            if (x.Value == y.Value)
                return 0;
            if (x.Value > y.Value)
                return -1;
            if (x.Value < y.Value)
                return 1;
            return 0;
        }
    }
    #endregion
}